package com.mcxx.modules.report.service.impl;

import com.google.common.collect.Maps;
import com.mcxx.common.ReportTargetEnum;
import com.mcxx.common.exception.BizException;
import com.mcxx.modules.base.service.read.AreaReadService;
import com.mcxx.modules.miniSalvation.fundpay.entity.FundPayEntity;
import com.mcxx.modules.miniSalvation.fundpay.param.FundPayListSearchParam;
import com.mcxx.modules.miniSalvation.fundpay.service.read.FundPayReadService;
import com.mcxx.modules.statistics.dto.CompareMinDTO;
import com.mcxx.modules.statistics.dto.ComparePovertyDTO;
import com.mcxx.modules.statistics.dto.CompareTempDTO;
import com.mcxx.modules.statistics.entity.FundPayReportCompare;
import com.mcxx.modules.statistics.service.read.ReportReadService;
import com.mcxx.modules.statistics.service.read.StatisticItemReadService;
import com.mcxx.modules.statistics.service.read.StatisticReadService;
import com.mcxx.util.AreaUtil;
import com.mcxx.util.CommonUtil;
import com.mcxx.util.Constant;
import com.mcxx.util.FailureCode;
import com.yinhai.ta404.component.org.orguser.area.entity.TaAreaPo;
import com.yinhai.ta404.core.transaction.annotation.TaTransactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


@Service
@TaTransactional
public class FundPayReportCompareService {

    private static final Logger logger = LoggerFactory.getLogger(FundPayReportCompareService.class);

    @Autowired
    private StatisticItemReadService statisticItemReadService;

    @Autowired
    private FundPayReadService fundPayReadService;

    @Autowired
    private AreaUtil areaUtil;

    @Autowired
    private StatisticReadService statisticReadService;

    @Autowired
    private ReportReadService reportReadService;

    @Autowired
    private AreaReadService areaReadService;



    public List<FundPayReportCompare> compareCountyLower(FundPayListSearchParam fundParams) {
        logger.info("开始比对农村低保综合统计报表数据");
        String reportName = ReportTargetEnum.COUNTY_LOWER.getReportName();
        String areaCode = fundParams.getAreaCode();

        List<TaAreaPo> taAreaPos = new ArrayList<TaAreaPo>();
        List<Integer> levels = new ArrayList<Integer>();

        commonStatisticStart(fundParams, taAreaPos, levels);


        String validCode = areaUtil.getValidCode(areaCode);
        fundParams.setAreaCode(validCode);
        fundParams.setFundType(Constant.FundType.CAPITAL_FUND_PAY);
        fundParams.setBusinessType(Constant.BusinessCode.DIBAO);
        fundParams.setStandType(Constant.BusinessStandType.COUNTY_DIBAO);
        fundParams.setExportType("0");//1.累计、0.当月
        fundParams.setStatus("1");


        List<CompareMinDTO> reportList = reportReadService.getCountyLowerReportData(areaUtil.getValidCode(taAreaPos.get(0).getAreaCode()), levels,
                fundParams.getPayDate(), Constant.StatisBusinessCode.COUNTY_DIBAO);

        List<FundPayReportCompare> resultList = new ArrayList<>();


        List<FundPayEntity> fundList = getCapitalFundPay(fundParams);

        countyMinCompareNumber(reportName, reportList, resultList, fundList, "本月低保人数", "memberNum", "subAllowances");



        countyMinCompareNumber(reportName, reportList, resultList, fundList, "本月低保户数", "households", "subFamilyNum");


        fundParams.setExportType("1");//1.累计、0.当月
        List<FundPayEntity> fundListSum = getCapitalFundPay(fundParams);

        countyMinCompareNumber(reportName, reportList, resultList, fundListSum, "1-当月累计农村低保保障人次", "memberNum", "subGuaranteeTimes");


        fundParams.setExportType("0");//1.累计、0.当月
        List<String> mulFundType = new ArrayList<>();
        mulFundType.add(Constant.FundType.STAND_FUND_PAY);
        mulFundType.add(Constant.FundType.CUSTOM_FUND_PAY);
        fundParams.setIdsList(mulFundType);
        List<FundPayEntity> fundListCurAppend = getCapitalFundPay(fundParams);

        countyMinCompareNumber(reportName, reportList, resultList, fundListCurAppend, "当月补发人次", "memberNum", "replacementNum");


        fundParams.setFundType(null);
        List<FundPayEntity> fundListPay = getCapitalFundPay(fundParams);

        countyMinCompareAmount(reportName, reportList, resultList, fundListPay, "农村低保当月支出", "payTotal", "subExpenditure");



        countyMinCompareAmount(reportName, reportList, resultList, fundList, "农村低保金", "payTotal", "subPay");


        fundParams.setFundType(Constant.FundType.CUSTOM_FUND_PAY);
        List<FundPayEntity> fundListTemp = getCapitalFundPay(fundParams);

        countyMinCompareAmount(reportName, reportList, resultList, fundListTemp, "农村低保临时补助", "payTotal", "subSubsidy");



        countyMinCompareAmount(reportName, reportList, resultList, fundListCurAppend, "农村低保补发资金", "payTotal", "subSubsidy");



        countyMinCompareAmount(reportName, reportList, resultList, fundListCurAppend, "1-当月农村低保累计支出", "payTotal", "total");
        logger.info("农村低保报表数据比对结束，误差数据，共{}条",reportList.size());
        return resultList;
    }



    public List<FundPayReportCompare> compareCityLower(FundPayListSearchParam fundParams) {
        logger.info("开始比对城市低保综合统计报表数据");
        String reportName = ReportTargetEnum.CITY_LOWER.getReportName();
        String areaCode = fundParams.getAreaCode();

        List<TaAreaPo> taAreaPos = new ArrayList<TaAreaPo>();
        List<Integer> levels = new ArrayList<Integer>();

        commonStatisticStart(fundParams, taAreaPos, levels);


        String validCode = areaUtil.getValidCode(areaCode);
        fundParams.setAreaCode(validCode);
        fundParams.setFundType(Constant.FundType.CAPITAL_FUND_PAY);
        fundParams.setBusinessType(Constant.BusinessCode.DIBAO);
        fundParams.setStandType(Constant.BusinessStandType.CITY_DIBAO);
        fundParams.setExportType("0");//1.累计、0.当月
        fundParams.setStatus("1");


        List<CompareMinDTO> reportList = reportReadService.getCityLowerReportData(areaUtil.getValidCode(taAreaPos.get(0).getAreaCode()), levels,
                fundParams.getPayDate(), Constant.StatisBusinessCode.CITY_DIBAO);

        List<FundPayReportCompare> resultList = new ArrayList<>();


        List<FundPayEntity> fundList = getCapitalFundPay(fundParams);

        countyMinCompareNumber(reportName, reportList, resultList, fundList, "本月低保人数", "memberNum", "subAllowances");



        countyMinCompareNumber(reportName, reportList, resultList, fundList, "本月低保户数", "households", "subFamilyNum");


        fundParams.setExportType("1");//1.累计、0.当月
        List<FundPayEntity> fundListSum = getCapitalFundPay(fundParams);

        countyMinCompareNumber(reportName, reportList, resultList, fundListSum, "1-当月累计农村低保保障人次", "memberNum", "subGuaranteeTimes");


        fundParams.setExportType("0");//1.累计、0.当月
        List<String> mulFundType = new ArrayList<>();
        mulFundType.add(Constant.FundType.STAND_FUND_PAY);
        mulFundType.add(Constant.FundType.CUSTOM_FUND_PAY);
        fundParams.setIdsList(mulFundType);
        List<FundPayEntity> fundListCurAppend = getCapitalFundPay(fundParams);

        countyMinCompareNumber(reportName, reportList, resultList, fundListCurAppend, "当月补发人次", "memberNum", "replacementNum");


        fundParams.setFundType(null);
        List<FundPayEntity> fundListPay = getCapitalFundPay(fundParams);

        countyMinCompareAmount(reportName, reportList, resultList, fundListPay, "城市低保当月支出", "payTotal", "subExpenditure");



        countyMinCompareAmount(reportName, reportList, resultList, fundList, "城市低保金", "payTotal", "subPay");


        fundParams.setFundType(Constant.FundType.CUSTOM_FUND_PAY);
        List<FundPayEntity> fundListTemp = getCapitalFundPay(fundParams);

        countyMinCompareAmount(reportName, reportList, resultList, fundListTemp, "城市低保临时补助", "payTotal", "subSubsidy");



        countyMinCompareAmount(reportName, reportList, resultList, fundListCurAppend, "城市低保补发资金", "payTotal", "subSubsidy");



        countyMinCompareAmount(reportName, reportList, resultList, fundListCurAppend, "1-当月城市低保累计支出", "payTotal", "total");
        logger.info("城市低保报表数据比对结束，误差数据，共{}条",reportList.size());
        return resultList;
    }



    public List<FundPayReportCompare> compareCountyPoverty(FundPayListSearchParam fundParams) {
        logger.info("开始比对农村特困综合统计报表数据");
        String reportName = ReportTargetEnum.COUNTY_POVERTY.getReportName();
        String areaCode = fundParams.getAreaCode();

        List<TaAreaPo> taAreaPos = new ArrayList<TaAreaPo>();
        List<Integer> levels = new ArrayList<Integer>();

        commonStatisticStart(fundParams, taAreaPos, levels);


        String validCode = areaUtil.getValidCode(areaCode);
        fundParams.setAreaCode(validCode);
        fundParams.setFundType(Constant.FundType.CAPITAL_FUND_PAY);
        fundParams.setBusinessType(Constant.BusinessCode.TEKUN);
        fundParams.setStandType(Constant.BusinessStandType.COUNTY_TEKUN);
        fundParams.setCostType(Constant.CapitalFundPayCostType.BASIC);
        fundParams.setExportType("1");//1.累计、0.当月
        fundParams.setStatus("1");


        List<ComparePovertyDTO> reportList = reportReadService.getExCountyReportData(areaUtil.getValidCode(taAreaPos.get(0).getAreaCode()), levels,
                fundParams.getPayDate(), Constant.StatisBusinessCode.TEKUN);

        List<FundPayReportCompare> resultList = new ArrayList<>();


        List<FundPayEntity> fundList = getCapitalFundPay(fundParams);

        countyPovertyCompareNumber(reportName, reportList, resultList, fundList, "1-本月累计保障人数", "memberNum", "cumulativeTimes");


        fundParams.setExportType("0");
        List<FundPayEntity> fundListCur = getCapitalFundPay(fundParams);

        countyPovertyCompareNumber(reportName, reportList, resultList, fundListCur, "当月保障人数", "memberNum", "povertyNum");


        fundParams.setSupplyType(Constant.SupplyType.SUPPLY_FOCUS);
        List<FundPayEntity> fundListFocus = getCapitalFundPay(fundParams);

        countyPovertyCompareNumber(reportName, reportList, resultList, fundListFocus, "当月集中供养人数", "memberNum", "focusNum");


        fundParams.setExportType("1");
        fundParams.setFundType(null);
        fundParams.setSupplyType(null);
        fundParams.setCostType(null);
        List<FundPayEntity> fundListPay = getCapitalFundPay(fundParams);

        countyPovertyCompareAmount(reportName, reportList, resultList, fundListPay, "1-本月累计支出资金", "payTotal", "total");


        fundParams.setExportType("1");
        fundParams.setFundType(Constant.FundType.FUNERAL_FUND_PAY);
        List<FundPayEntity> fundListFuneral = getCapitalFundPay(fundParams);

        countyPovertyCompareAmount(reportName, reportList, resultList, fundListFuneral, "1-当月丧葬费", "payTotal", "funeralPay");


        fundParams.setFundType(Constant.FundType.STAND_FUND_PAY);
        fundParams.setCostType(Constant.CapitalFundPayCostType.BASIC);
        List<FundPayEntity> fundListPayAppend = getCapitalFundPay(fundParams);

        countyPovertyCompareAmount(reportName, reportList, resultList, fundListPayAppend, "1-本月累计补发支出资金", "payTotal", "subTotal");
        logger.info("农村特困综合统计报表数据比对结束，误差数据，共{}条",reportList.size());
        return resultList;
    }


    public List<FundPayReportCompare> compareCityPoverty(FundPayListSearchParam fundParams) {
        logger.info("开始比对城市特困综合统计报表数据");
        String reportName = ReportTargetEnum.CITY_POVERTY.getReportName();
        String areaCode = fundParams.getAreaCode();

        List<TaAreaPo> taAreaPos = new ArrayList<TaAreaPo>();
        List<Integer> levels = new ArrayList<Integer>();

        commonStatisticStart(fundParams, taAreaPos, levels);


        String validCode = areaUtil.getValidCode(areaCode);
        fundParams.setAreaCode(validCode);
        fundParams.setFundType(Constant.FundType.CAPITAL_FUND_PAY);
        fundParams.setBusinessType(Constant.BusinessCode.TEKUN);
        fundParams.setStandType(Constant.BusinessStandType.CITY_TEKUN);
        fundParams.setCostType(Constant.CapitalFundPayCostType.BASIC);
        fundParams.setExportType("1");//1.累计、0.当月
        fundParams.setStatus("1");


        List<ComparePovertyDTO> reportList = reportReadService.getExCityReportData(areaUtil.getValidCode(taAreaPos.get(0).getAreaCode()), levels,
                fundParams.getPayDate(), Constant.StatisBusinessCode.TEKUN);

        List<FundPayReportCompare> resultList = new ArrayList<>();


        List<FundPayEntity> fundList = getCapitalFundPay(fundParams);

        countyPovertyCompareNumber(reportName, reportList, resultList, fundList, "1-本月累计保障人数", "memberNum", "cumulativeTimes");


        fundParams.setExportType("0");
        List<FundPayEntity> fundListCur = getCapitalFundPay(fundParams);

        countyPovertyCompareNumber(reportName, reportList, resultList, fundListCur, "当月保障人数", "memberNum", "povertyNum");


        fundParams.setSupplyType(Constant.SupplyType.SUPPLY_FOCUS);
        List<FundPayEntity> fundListFocus = getCapitalFundPay(fundParams);

        countyPovertyCompareNumber(reportName, reportList, resultList, fundListFocus, "当月集中供养人数", "memberNum", "focusNum");


        fundParams.setExportType("1");
        fundParams.setFundType(null);
        fundParams.setSupplyType(null);
        fundParams.setCostType(null);
        List<FundPayEntity> fundListPay = getCapitalFundPay(fundParams);

        countyPovertyCompareAmount(reportName, reportList, resultList, fundListPay, "1-本月累计支出资金", "payTotal", "total");


        fundParams.setExportType("1");
        fundParams.setFundType(Constant.FundType.FUNERAL_FUND_PAY);
        List<FundPayEntity> fundListFuneral = getCapitalFundPay(fundParams);

        countyPovertyCompareAmount(reportName, reportList, resultList, fundListFuneral, "1-当月丧葬费", "payTotal", "funeralPay");


        fundParams.setFundType(Constant.FundType.STAND_FUND_PAY);
        fundParams.setCostType(Constant.CapitalFundPayCostType.BASIC);
        List<FundPayEntity> fundListPayAppend = getCapitalFundPay(fundParams);

        countyPovertyCompareAmount(reportName, reportList, resultList, fundListPayAppend, "1-本月累计补发支出资金", "payTotal", "subTotal");
        logger.info("城市特困综合统计报表数据比对结束，误差数据，共{}条",reportList.size());
        return resultList;
    }


    public List<FundPayReportCompare> compareTemp(FundPayListSearchParam fundParams) {
        logger.info("开始比对临时救助综合统计报表数据");
        String reportName = ReportTargetEnum.TEMP.getReportName();
        String areaCode = fundParams.getAreaCode();

        List<TaAreaPo> taAreaPos = new ArrayList<TaAreaPo>();
        List<Integer> levels = new ArrayList<Integer>();

        commonStatisticStart(fundParams, taAreaPos, levels);


        String validCode = areaUtil.getValidCode(areaCode);
        fundParams.setAreaCode(validCode);
        fundParams.setExportType("1");//1.累计、0.当月


        List<CompareTempDTO> reportList = reportReadService.getTempReportData(areaUtil.getValidCode(taAreaPos.get(0).getAreaCode()), levels, fundParams.getPayDate());

        List<FundPayReportCompare> resultList = new ArrayList<>();


        List<FundPayEntity> fundList = getTempFundPay(fundParams);

        tempCompareNumber(reportName, reportList, resultList, fundList, "临时救助对象", "memberNum", "tempNum");








        tempCompareAmount(reportName, reportList, resultList, fundList, "临时救助累计支出", "payTotal", "total");








        tempCompareStandard(reportName, reportList, resultList, fundList, "临时救助救助水平", "payTotal", "total");
        logger.info("临时救助综合统计报表数据比对结束，误差数据，共{}条",reportList.size());
        return resultList;
    }


    private List<FundPayEntity> getTempFundPay(FundPayListSearchParam param) {
        List<FundPayEntity> results = new ArrayList<>();


        String yearMonth = param.getPayDate();
        String payDate = yearMonth.substring(0, 4) + "-" + yearMonth.substring(4) + "-01";
        param.setPayDate(payDate);


        List<FundPayEntity> list = new ArrayList<>();
        if ("1".equals(param.getExportType())) {
            int m = Integer.parseInt(yearMonth.substring(4));
            List<String> payDates = new ArrayList<>();
            for (int i = 1; i <= m; i++) {
                String pd = yearMonth.substring(0, 4) + "-0" + i + "-01";
                payDates.add(pd);
            }
            for (String pd : payDates) {
                param.setPayDate(pd);
                List<FundPayEntity> l = fundPayReadService.getTempFundPay(param);
                list.addAll(l);
            }
        } else {
            list = fundPayReadService.getTempFundPay(param);
        }

        sumTempFundPay(results, list);


        param.setPayDate(yearMonth);
        return results;
    }


    private void sumTempFundPay(List<FundPayEntity> results, List<FundPayEntity> list) {

        List<FundPayEntity> notNull = list.stream().filter(e -> e.getArea() != null)
                .collect(Collectors.toList());
        Map<String, List<FundPayEntity>> areaCodeMap = notNull.stream().collect(Collectors.groupingBy(FundPayEntity::getArea));
        Set<String> keySet = areaCodeMap.keySet();
        Iterator<String> it = keySet.iterator();
        while (it.hasNext()) {
            String key = it.next();
            List<FundPayEntity> rollList = areaCodeMap.get(key);
            FundPayEntity roll = new FundPayEntity();
            BeanUtils.copyProperties(rollList.get(0), roll);
            String areaCode = rollList.get(0).getAreaCode();
            roll.setAreaCode(key);
            roll.setArea(areaCode);

            Integer house = rollList.stream().mapToInt(e -> null == e.getHouseholds() ? 0 : e.getHouseholds()).sum();
            Integer member = rollList.stream().mapToInt(e -> null == e.getMemberNum() ? 0 : e.getMemberNum()).sum();
            Double amount = rollList.stream().mapToDouble(e -> null == e.getPayTotal() ? 0 : e.getPayTotal()).sum();
            roll.setHouseholds(house);
            roll.setMemberNum(member);
            roll.setPayTotal(amount / 10000);
            results.add(roll);
        }
    }


    private void sumFundPay(List<FundPayEntity> results, List<FundPayEntity> list) {

        List<FundPayEntity> notNull = list.stream().filter(e -> e.getArea() != null)
                .collect(Collectors.toList());
        Map<String, List<FundPayEntity>> areaCodeMap = notNull.stream().collect(Collectors.groupingBy(FundPayEntity::getAreaCode));
        Set<String> keySet = areaCodeMap.keySet();
        Iterator<String> it = keySet.iterator();
        while (it.hasNext()) {
            String key = it.next();
            List<FundPayEntity> rollList = areaCodeMap.get(key);
            FundPayEntity roll = new FundPayEntity();
            BeanUtils.copyProperties(rollList.get(0), roll);

            Integer house = rollList.stream().mapToInt(e -> null == e.getHouseholds() ? 0 : e.getHouseholds()).sum();
            Integer member = rollList.stream().mapToInt(e -> null == e.getMemberNum() ? 0 : e.getMemberNum()).sum();
            Double amount = rollList.stream().mapToDouble(e -> null == e.getPayTotal() ? 0 : e.getPayTotal()).sum();
            roll.setHouseholds(house);
            roll.setMemberNum(member);
            roll.setPayTotal(amount / 10000);
            results.add(roll);
        }
    }



    public String commonStatisticStart(FundPayListSearchParam param, List<TaAreaPo> taAreaPos,
                                       List<Integer> levels) {
        if (CommonUtil.invalidArgs(param.getPayDate()) || param.getPayDate().length() != 6) {
            throw new BizException(FailureCode.ERR_10001);
        }



        TaAreaPo curTaAreaPo = null;
        StringBuilder name = new StringBuilder();
        List<String> areaCodes = areaUtil.getNodeTreePathFromRoot(param.getAreaCode());
        for (String code : areaCodes) {
            TaAreaPo taAreaPro = areaReadService.getAreaByCode(code);
            if (null != taAreaPro)
                name.append(taAreaPro.getAreaName());

            if (code.equals(param.getAreaCode())) {
                curTaAreaPo = taAreaPro;
            }
        }

        if (null == curTaAreaPo) {
            throw new BizException(FailureCode.ERR_100001);
        }

        name.append(param.getPayDate().substring(0, 4)).append("年").append(param.getPayDate().substring(4)).append("月");



        if (null != taAreaPos)
            taAreaPos.add(curTaAreaPo);

        if (null != levels && null != taAreaPos) {
            levels.add(curTaAreaPo.getAreaLevel());
            if (curTaAreaPo.getAreaLevel().equals(Constant.AreaLevel.PROVINCE)) {
                taAreaPos.addAll(areaReadService.getChildrenByLevel(
                        areaUtil.getValidCode(curTaAreaPo.getAreaCode(), curTaAreaPo.getAreaLevel()),
                        Arrays.asList(curTaAreaPo.getAreaLevel() + 1, curTaAreaPo.getAreaLevel() + 2)));
                levels.add(curTaAreaPo.getAreaLevel() + 1);
                levels.add(curTaAreaPo.getAreaLevel() + 2);
            } else {
                if (curTaAreaPo.getAreaLevel() < Constant.AreaLevel.COMMUNITY) {
                    taAreaPos.addAll(areaReadService.getChildrenByLevel(
                            areaUtil.getValidCode(curTaAreaPo.getAreaCode(), curTaAreaPo.getAreaLevel()),
                            Collections.singletonList(curTaAreaPo.getAreaLevel() + 1)));
                    levels.add(curTaAreaPo.getAreaLevel() + 1);
                }
            }

            if (taAreaPos.isEmpty() || levels.isEmpty() || name.toString().isEmpty()) {
                throw new BizException(FailureCode.ERR_100002);
            }
        }

        return name.toString();
    }


    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = Maps.newHashMap();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key + "", beanMap.get(key));
            }
        }
        return map;
    }



    private void countyPovertyCompareNumber(String reportName, List<ComparePovertyDTO> reportList,
                                            List<FundPayReportCompare> resultList,
                                            List<FundPayEntity> fundList,
                                            String reportTarget,
                                            String keyRoll,
                                            String key) {
        for (FundPayEntity obj : fundList) {
            ComparePovertyDTO reportObj = getComparePovertyDTO(reportList, obj);
            if (reportObj == null) continue;
            Map<String, Object> objMap = beanToMap(obj);
            Map<String, Object> reportMap = beanToMap(reportObj);
            if (!objMap.get(keyRoll).equals(reportMap.get(key))) {

                Integer reObj = (Integer) reportMap.get(key);
                Integer objAmount = (Integer) objMap.get(keyRoll);
                Integer sub = reObj - objAmount;
                FundPayReportCompare compareDTO = FundPayReportCompare.generateDTOByCondition(obj, sub, reportName, reportTarget);
                resultList.add(compareDTO);
            }
        }
    }


    private CompareMinDTO getCompareMinDTO(List<CompareMinDTO> reportList, FundPayEntity obj) {
        Optional<CompareMinDTO> targetReport = reportList.stream().filter(item -> item.getAreaCode().equals(obj.getArea())).findFirst();
        CompareMinDTO reportObj = null;
        if (targetReport.isPresent()) {
            reportObj = targetReport.get();
        } else {
            return null;
        }
        return reportObj;
    }


    private void countyMinCompareAmount(String reportName, List<CompareMinDTO> reportList,
                                        List<FundPayReportCompare> resultList,
                                        List<FundPayEntity> fundList,
                                        String reportTarget,
                                        String keyRoll,
                                        String key) {
        for (FundPayEntity obj : fundList) {

            CompareMinDTO reportObj = getCompareMinDTO(reportList, obj);
            if (reportObj == null) continue;
            Map<String, Object> objMap = beanToMap(obj);
            Map<String, Object> reportMap = beanToMap(reportObj);
            if (!objMap.get(keyRoll).equals(reportMap.get(key))) {

                Double reObj = (Double) reportMap.get(key);
                Double objAmount = (Double) objMap.get(keyRoll);
                Double sub = BigDecimal.valueOf(reObj).subtract(BigDecimal.valueOf(objAmount)).doubleValue();
                FundPayReportCompare compareDTO = FundPayReportCompare.generateDTOByCondition(obj, sub, reportName, reportTarget);
                resultList.add(compareDTO);
            }
        }
    }



    private void countyMinCompareNumber(String reportName, List<CompareMinDTO> reportList,
                                        List<FundPayReportCompare> resultList,
                                        List<FundPayEntity> fundList,
                                        String reportTarget,
                                        String keyRoll,
                                        String key) {
        for (FundPayEntity obj : fundList) {
            CompareMinDTO reportObj = getCompareMinDTO(reportList, obj);
            if (reportObj == null) continue;
            Map<String, Object> objMap = beanToMap(obj);
            Map<String, Object> reportMap = beanToMap(reportObj);
            if (!objMap.get(keyRoll).equals(reportMap.get(key))) {

                Integer reObj = (Integer) reportMap.get(key);
                Integer objAmount = (Integer) objMap.get(keyRoll);
                Integer sub = reObj - objAmount;
                FundPayReportCompare compareDTO = FundPayReportCompare.generateDTOByCondition(obj, sub, reportName, reportTarget);
                resultList.add(compareDTO);
            }
        }
    }


    private ComparePovertyDTO getComparePovertyDTO(List<ComparePovertyDTO> reportList, FundPayEntity obj) {
        Optional<ComparePovertyDTO> targetReport = reportList.stream().filter(item -> item.getAreaCode().equals(obj.getArea())).findFirst();
        ComparePovertyDTO reportObj = null;
        if (targetReport.isPresent()) {
            reportObj = targetReport.get();
        } else {
            return null;
        }
        return reportObj;
    }


    private CompareTempDTO getCompareTempDTO(List<CompareTempDTO> reportList, FundPayEntity obj) {
        Optional<CompareTempDTO> targetReport = reportList.stream().filter(item -> item.getAreaCode().equals(obj.getAreaCode())).findFirst();
        CompareTempDTO reportObj = null;
        if (targetReport.isPresent()) {
            reportObj = targetReport.get();
        } else {
            return null;
        }
        return reportObj;
    }


    private void countyPovertyCompareAmount(String reportName, List<ComparePovertyDTO> reportList,
                                            List<FundPayReportCompare> resultList,
                                            List<FundPayEntity> fundList,
                                            String reportTarget,
                                            String keyRoll,
                                            String key) {
        for (FundPayEntity obj : fundList) {

            ComparePovertyDTO reportObj = getComparePovertyDTO(reportList, obj);
            if (reportObj == null) continue;
            Map<String, Object> objMap = beanToMap(obj);
            Map<String, Object> reportMap = beanToMap(reportObj);
            if (!objMap.get(keyRoll).equals(reportMap.get(key))) {

                Double reObj = (Double) reportMap.get(key);
                Double objAmount = (Double) objMap.get(keyRoll);
                Double sub = BigDecimal.valueOf(reObj).subtract(BigDecimal.valueOf(objAmount)).doubleValue();
                FundPayReportCompare compareDTO = FundPayReportCompare.generateDTOByCondition(obj, sub, reportName, reportTarget);
                resultList.add(compareDTO);
            }
        }
    }



    private List<FundPayEntity> getCapitalFundPay(FundPayListSearchParam param) {
        List<FundPayEntity> results = new ArrayList<>();


        String yearMonth = param.getPayDate();
        String payDate = yearMonth.substring(0, 4) + "-" + yearMonth.substring(4) + "-01";
        param.setPayDate(payDate);

        List<String> fundTypes = param.getIdsList();
        param.setIdsList(null);
        if (null != fundTypes && !fundTypes.isEmpty()) {
            for (String fundType : fundTypes) {
                param.setFundType(fundType);
                sumRollData(param, results, yearMonth);
            }
        } else {
            sumRollData(param, results, yearMonth);
        }

        param.setPayDate(yearMonth);
        return results;
    }


    private void sumRollData(FundPayListSearchParam param, List<FundPayEntity> results, String yearMonth) {

        List<FundPayEntity> list = new ArrayList<>();
        if ("1".equals(param.getExportType())) {
            int m = Integer.parseInt(yearMonth.substring(4));
            List<String> payDates = new ArrayList<>();
            for (int i = 1; i <= m; i++) {
                String pd = yearMonth.substring(0, 4) + "-0" + i + "-01";
                payDates.add(pd);
            }
            for (String pd : payDates) {
                param.setPayDate(pd);
                List<FundPayEntity> l = fundPayReadService.getFundPayList(param);
                list.addAll(l);
            }
        } else {
            list = fundPayReadService.getFundPayList(param);
        }

        sumFundPay(results, list);
    }



    private void tempCompareAmount(String reportName, List<CompareTempDTO> reportList,
                                            List<FundPayReportCompare> resultList,
                                            List<FundPayEntity> fundList,
                                            String reportTarget,
                                            String keyRoll,
                                            String key) {
        for (FundPayEntity obj : fundList) {
            CompareTempDTO reportObj = getCompareTempDTO(reportList, obj);
            if (reportObj == null) continue;
            Map<String, Object> objMap = beanToMap(obj);
            Map<String, Object> reportMap = beanToMap(reportObj);
            if (!objMap.get(keyRoll).equals(reportMap.get(key))) {

                Double reObj = (Double) reportMap.get(key);
                Double objAmount = (Double) objMap.get(keyRoll);
                Double sub = BigDecimal.valueOf(reObj).subtract(BigDecimal.valueOf(objAmount)).doubleValue();
                FundPayReportCompare compareDTO = FundPayReportCompare.generateDTOByCondition(obj, sub, reportName, reportTarget);
                resultList.add(compareDTO);
            }
        }
    }


    private void tempCompareNumber(String reportName, List<CompareTempDTO> reportList,
                                   List<FundPayReportCompare> resultList,
                                   List<FundPayEntity> fundList,
                                   String reportTarget,
                                   String keyRoll,
                                   String key) {
        for (FundPayEntity obj : fundList) {
            CompareTempDTO reportObj = getCompareTempDTO(reportList, obj);
            if (reportObj == null) continue;
            Map<String, Object> objMap = beanToMap(obj);
            Map<String, Object> reportMap = beanToMap(reportObj);
            if (!objMap.get(keyRoll).equals(reportMap.get(key))) {

                Integer reObj = (Integer) reportMap.get(key);
                Integer objAmount = (Integer) objMap.get(keyRoll);
                Integer sub = reObj - objAmount;
                FundPayReportCompare compareDTO = FundPayReportCompare.generateDTOByCondition(obj, sub, reportName, reportTarget);
                resultList.add(compareDTO);
            }
        }
    }

    private void tempCompareStandard(String reportName, List<CompareTempDTO> reportList,
                                   List<FundPayReportCompare> resultList,
                                   List<FundPayEntity> fundList,
                                   String reportTarget,
                                   String keyRoll,
                                   String key) {
        for (FundPayEntity obj : fundList) {
            CompareTempDTO reportObj = getCompareTempDTO(reportList, obj);
            if (reportObj == null) continue;
            Map<String, Object> objMap = beanToMap(obj);
            Map<String, Object> reportMap = beanToMap(reportObj);
            if (!objMap.get(keyRoll).equals(reportMap.get(key))) {

                Double reObj = (Double) reportMap.get(key);
                Double objAmount = (Double) objMap.get(keyRoll);
                Integer objNum = (Integer) objMap.get("memberNum");
                Double sub = BigDecimal.valueOf(reObj).subtract(BigDecimal.valueOf(objAmount).divide(BigDecimal.valueOf(objNum),2)).doubleValue();
                FundPayReportCompare compareDTO = FundPayReportCompare.generateDTOByCondition(obj, sub, reportName, reportTarget);
                resultList.add(compareDTO);
            }
        }
    }
}
